import subprocess
import os
import shutil
import stat
import datetime


# 克隆指定仓库
def clone_repo(repo_url: str) -> None:
    try:
        print(f"正在克隆仓库{repo_url}")
        subprocess.run(["git", "clone", repo_url], check=True)
        print(f"仓库{repo_url}克隆成功")
    except subprocess.CalledProcessError as err:
        print(f"仓库{repo_url}克隆失败，原因：{err}")


# 检查文件夹是否存在
def folder_exist(folder_path: str) -> bool:
    return os.path.isdir(folder_path)


# 删除指定文件夹
def delete_folder(folder_path: str) -> None:
    # 检查文件夹是否存在
    if folder_exist(folder_path):
        try:
            shutil.rmtree(folder_path, onerror=handle_readonly_error)  # 删除文件夹
        except OSError as err:
            print(f"删除文件夹{folder_path}失败，原因：{err}")


# 只读文件处理
def handle_readonly_error(func, file_path, exc_info) -> None:
    # 检查是否是权限错误
    if isinstance(exc_info[1], PermissionError):
        try:
            # 移除只读属性（添加写权限）
            os.chmod(file_path, stat.S_IWRITE)
            # 再次尝试执行原操作
            func(file_path)
        except Exception as err:
            print(f"处理 {file_path} 时出错: {err}")

    # 其他错误直接抛出
    else:
        raise


# 获取指定文件夹内所有条目的名称
def get_folder_items(folder_path):
    # 检查路径是否存在
    if not os.path.exists(folder_path):
        raise FileNotFoundError(f"路径 '{folder_path}' 不存在")

    # 检查路径是否是文件夹
    if not os.path.isdir(folder_path):
        raise NotADirectoryError(f"'{folder_path}' 不是一个文件夹")

    try:
        # 获取文件夹内所有条目名称
        items = os.listdir(folder_path)
        result = []

        # 去后缀处理
        for item in items:
            item_path = os.path.join(folder_path, item)
            # 检查是否为文件
            if os.path.isfile(item_path):
                # 这是只有后缀的文件，跳过不添加
                if item.startswith('.') and len(item.split('.', 1)) == 2 and item.split('.', 1)[0] == '':
                    continue

                # 分离文件名和后缀，只取文件名部分
                file_name_without_ext = os.path.splitext(item)[0]
                file_name_without_ext.strip(" ")
                result.append(file_name_without_ext)
            else:
                # 文件夹直接添加原名称
                result.append(item)

        return result
    except PermissionError:
        raise PermissionError(f"没有访问 '{folder_path}' 的权限")
    except OSError as e:
        raise OSError(f"访问 '{folder_path}' 时发生错误: {e}")


# 学生类
class Student:
    # 初始化
    def __init__(self, stu_name: str) -> None:
        self.__stu_name: str = stu_name           # 学生姓名
        self.__submit_cnt: list[int] = [0] * 13   # 每类提交次数
        self.__submit_cnt_sum: int = 0            # 总提交次数

    # 更新
    def updata(self, kind: int) -> None:
        self.__submit_cnt[kind] += 1
        self.__submit_cnt_sum += 1

    # 外部只读方式
    @property
    def stu_name(self) -> str:
        return self.__stu_name

    @property
    def submit_cnt(self) -> list[int]:
        return self.__submit_cnt

    @property
    def submit_cnt_sum(self) -> int:
        return self.__submit_cnt_sum

    # 打印函数
    def __str__(self) -> str:
        return f"学生姓名：{self.__stu_name}，每类提交次数：{self.__submit_cnt}，总提交次数：{self.__submit_cnt_sum}"

    def __repr__(self) -> str:
        return self.__str__()


# 生成学生提交次数的静态HTML表格
def generate_student_html(students: list[Student], filename: str) -> None:
    # 1. 构建HTML表头（包含“姓名”+“13类提交”+“总计”）
    th_tags = ['<th>排名</th>''<th>学生姓名</th>', '<th>exercise</th>']
    # 添加1-12类提交的表头（如“提交类型1”“提交类型2”...）
    th_tags.extend([f'<th>topic{_:02d}</th>' for _ in range(1, 13)])
    th_tags.append('<th>总提交次数</th>')  # 最后一列：总计
    table_header = ''.join(th_tags)

    # 2. 构建HTML表格内容（遍历每个学生实例）
    tr_tags = []
    last_score, ranking = students[0].submit_cnt_sum, 1
    for index, stu in enumerate(students):
        if stu.stu_name == "姓名": continue

        # 检查并列
        if stu.submit_cnt_sum == last_score:
            td_list = [f'<td>{ranking}</td>']
        else:
            ranking = index + 1
            td_list = [f'<td>{index + 1}</td>']
        last_score = stu.submit_cnt_sum
        # 每行第一列：学生姓名
        td_list.extend([f'<td>{stu.stu_name}</td>'])
        # 中间13列：每类提交次数（按submit_cnt顺序）
        td_list.extend([f'<td>{cnt}</td>' for cnt in stu.submit_cnt])
        # 最后一列：总提交次数
        td_list.append(f'<td>{stu.submit_cnt_sum}</td>')
        # 组合当前行的HTML标签
        tr_tags.append(f'<tr>{"".join(td_list)}</tr>')
    table_body = ''.join(tr_tags)

    # 3. 完整HTML结构（包含基础样式，优化表格可读性）
    html_content = f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>学生提交次数统计</title>
    <style>
        /* 表格基础样式 */
        table {{
            width: 90%;
            margin: 20px auto;  /* 居中显示 */
            border-collapse: collapse;  /* 合并边框 */
            font-family: "Microsoft YaHei", sans-serif;
        }}
        /* 表头样式 */
        th {{
            background-color: #4CAF50;  /* 绿色表头 */
            color: white;
            padding: 12px;
            text-align: center;
            border: 1px solid #ddd;
        }}
        /* 表格内容样式 */
        td {{
            padding: 10px;
            text-align: center;
            border: 1px solid #ddd;
        }}
        /* 交替行背景色（提升可读性） */
        tr:nth-child(even) {{
            background-color: #f2f2f2;
        }}
        /* 鼠标悬浮行高亮 */
        tr:hover {{
            background-color: #ddd;
        }}
        /* 页面标题样式 */
        h1 {{
            text-align: center;
            color: #333;
            margin-top: 30px;
        }}
    </style>
</head>
<body>
    <h1>学生各类任务提交次数统计</h1>
    <table>
        <thead>
            <tr>{table_header}</tr>
        </thead>
        <tbody>
            {table_body}
        </tbody>
    </table>
</body>
</html>
'''

    # 4. 将HTML内容写入文件
    with open(f"{filename}.html", 'w', encoding='utf-8') as f:
        f.write(html_content)


if __name__ == "__main__":
    # 仓库地址
    repository: str = "https://gitee.com/gcu-acm/algorithm-training-202509.git"
    # 学生统计信息
    stu_cnt_info: dict[str: Student] = dict()

    # 主程序
    while True:
        # 提示词
        print("---欢迎使用Gitee仓库分析脚本---")
        print("1.更新仓库")
        print("2.分析仓库")
        print("3.退出脚本")
        choice = input("请选择（1、2或3）：")

        # 更新仓库
        if choice == "1":
            # 检查本地是否存在仓库，有就删除
            delete_folder("algorithm-training-202509")

            # 拉取仓库
            clone_repo(repository)
            print("仓库更新完毕")

        # 分析仓库
        elif choice == "2":
            # 清空缓存
            stu_cnt_info.clear()

            # 仓库编号0-12，0号仓库单独处理
            for index in range(13):
                if index == 0:
                    try:
                        files_name = get_folder_items("algorithm-training-202509\\exercise")
                    except:
                        print("没有仓库可供分析")
                        break

                    # 提取关键信息
                    for i in range(len(files_name)):
                        files_name[i] = files_name[i].split("_")[-1].strip(" ")

                    for name in files_name:
                        # 确保名字存在
                        if name not in stu_cnt_info:
                            stu_cnt_info[name] = Student(name)

                        # 更新计数
                        stu_cnt_info[name].updata(index)

                else:
                    try:
                        files_name = get_folder_items(F"algorithm-training-202509\\topic{index:02d}\\submit")
                    except:
                        print("没有仓库可供分析")
                        break

                    # 提取关键信息
                    for i in range(len(files_name)):
                        files_name[i] = files_name[i].split("_")[-1].strip(" ")

                    for name in files_name:
                        # 确保名字存在
                        if name not in stu_cnt_info:
                            stu_cnt_info[name] = Student(name)

                        # 更新计数
                        stu_cnt_info[name].updata(index)
            else:
                # 提取Student实例并根据总提交排序
                students = list(stu_cnt_info.values())
                students.sort(key=lambda x: x.submit_cnt_sum, reverse=True)

                # 制作静态网页表格（HTML文件）
                generate_student_html(students, f"24级提交统计数据-{str(datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S"))}")
                print(f"文件“24级提交统计数据-{str(datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S"))}”制作完成")

        elif choice == "3":
            break

        # 其他情况
        else:
            print("无效输入，请重新选择")

    # 退出提示
    print("脚本结束运行")
